﻿
/***************************************************************************

Copyright (c) BizRulX. All rights reserved.

***************************************************************************/

using System;
using System.Windows.Forms;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using tom;
using System.Collections.Generic;
using System.Drawing;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio;


namespace RuleXSoft.BizRuleCreator
{
    public partial class MyEditor : UserControl
    {
        private const int GetOleInterfaceCommandId = 1084;

        private string m_TextToRecord;
        private VSMacroRecorder m_Recorder;

        public bool IsNewRowValidated { get; set; }
        public string RulXFile { get; set; }

        private Dictionary<string,string> objRulXFieldList = null;
        private Dictionary<string, Dictionary<string, string>> objRuleXFieldList = null;

        public RulXActionEnum Action { get; set; }

        public Dictionary<string, Dictionary<string, string>> NewRuleXFieldValueList
        {
            get { return objRuleXFieldList; }
            set { objRuleXFieldList = value; }
        }

        public string KeyFieldName { get; set; }
        public string FieldUpdatedValue { get; set; }
        public string FieldOldValue { get; set; }
        public string RuleID { get; set; }

        public int NewAddedRowIndex { get; set; }
        public int NewAddedRowIndexOnPaste { get; set; }
        public string NewRuleID { get; set; }
        public int ClickedRowIndex { get; set; }
        public int RulXPasteRowIndex { get; set; }

        RulXAttributeObject objRulXAtt = null;
        Dictionary<string, RulXAttributeObject> objRulXAttributeList = null;
        List<RulXAttributeObject> objRuleXAttributeList = null;

        public Dictionary<string, RulXAttributeObject> RulXAttributeList
        {
            get { return objRulXAttributeList; }
            set { objRulXAttributeList = value; }
        }

        public List<RulXAttributeObject> RuleXAttributeList
        {
            get { return objRuleXAttributeList; }
            set { objRuleXAttributeList = value; }
        }
        

        public MyEditor()
        {
            InitializeComponent();
            this.richTextBoxCtrl.WordWrap = false;
            this.richTextBoxCtrl.HideSelection = false;
            
            m_Recorder = new VSMacroRecorder(GuidList.guidBizRuleXVS2010EditorFactory);

            
            objRulXAttributeList = new Dictionary<string, RulXAttributeObject>();
            objRuleXAttributeList = new List<RulXAttributeObject>();
            this.DataGridViewControl.DataError += new DataGridViewDataErrorEventHandler(DataGridViewControl_DataError);
            rulXGridView.NewRowNeeded+=new DataGridViewRowEventHandler(rulXGridView_NewRowNeeded);

            NewAddedRowIndex = -1;
            ClickedRowIndex = -1;
            IsNewRowValidated = true;

            //rulXGridView.Width = this.Width;
            InitializeContextMenu();

            this.rulXGridView.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
            //this.rulXGridView.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
            objRuleXFieldList = new Dictionary<string, Dictionary<string, string>>();

            this.toolStripButtonDelRule.Enabled = false;
        }

        void DataGridViewControl_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            
        }

        public EditorTextBox RichTextBoxControl
        {
            get { return this.richTextBoxCtrl; }
        }

        public DataGridView DataGridViewControl
        {
            get { return this.rulXGridView; }
        }

        /// <summary>
        /// Gets the default size of a given window pane.
        /// </summary>
        /// <param name="pSize">The size of a given window pane.</param>
        /// <returns>S_OK if the method succeeds.</returns> 
        public int GetDefaultSize(SIZE[] pSize)
        {
            if (pSize != null && pSize.Length >= 1)
            {
                pSize[0].cx = Size.Width;
                pSize[0].cy = Size.Height;
            }

            return VSConstants.S_OK;
        }

        #region Fields

        /// <summary>
        /// This value is used internally so that we know what to display on the status bar.
        /// NOTE: Setting this value will not actually change the insert/overwrite behavior
        /// of the editor, it is just used so that we can keep track of the state internally.
        /// </summary>
        private bool overstrike;
        public bool Overstrike
        {
            get
            {
                return this.overstrike;
            }
            set
            {
                this.overstrike = value;
            }
        }

        private ITextDocument textDocument;

        /// <summary>
        /// This property exposes the ITextDocument interface associated with
        /// our Rich Text editor.
        /// </summary>
        public ITextDocument TextDocument
        {
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            get
            {
                if (null != textDocument)
                    return textDocument;

                // To get the IRichEditOle interface we need to call SendMessage, which
                // we imported from user32.dll
                object editOle = null;
                NativeMethods.SendMessage(richTextBoxCtrl.Handle,                // The rich text box handle
                                          GetOleInterfaceCommandId,   // The command ID for EM_GETOLEINTERFACE
                                          IntPtr.Zero,                // null
                                          out editOle                 // This will be set to the IRichEditOle interface
                                          );

                // Call GetIUnknownForObject with the IRichEditOle interface that we
                // just got so that we have an IntPtr to pass into QueryInterface
                IntPtr editOlePtr = IntPtr.Zero;
                editOlePtr = Marshal.GetIUnknownForObject(editOle);

                // Call QueryInterface to get the pointer to the ITextDocument
                IntPtr iTextDocument = IntPtr.Zero;
                Guid iTextDocumentGuid = typeof(ITextDocument).GUID;
                Marshal.QueryInterface(editOlePtr, ref iTextDocumentGuid, out iTextDocument);

                // We need to call Marshal.Release with the pointer that we got
                // from the GetIUnknownForObject call
                Marshal.Release(editOlePtr);

                // Call GetObjectForIUnknown passing in the pointer that was set
                // by QueryInterface and return it as an ITextDocument
                textDocument = Marshal.GetObjectForIUnknown(iTextDocument) as ITextDocument;
                return textDocument;
            }
        }

        /// <summary>
        /// This property will return the current ITextRange interface.
        /// </summary>
        public ITextRange TextRange
        {
            get
            {
                return this.TextDocument.Range(0, (int)tom.tomConstants.tomForward);
            }
        }

        /// <summary>
        /// This property will return the current ITextSelection interface.
        /// </summary>
        public ITextSelection TextSelection
        {
            get
            {
                return this.TextDocument.Selection;
            }
        }

        #endregion

        /// <summary>
        /// Returns the column number from the specified index
        /// </summary>
        /// <param name="index">index of the character</param>
        /// <returns>column number</returns>
        public int GetColumnFromIndex(int index)
        {
            //first get the index of the first char of the current line
            int currentLineIndex = richTextBoxCtrl.GetFirstCharIndexOfCurrentLine();
            return index - currentLineIndex;
        }

        /// <summary>
        /// Returns the index from the specified line and column number
        /// </summary>
        /// <param name="line">line number</param>
        /// <param name="column">column number</param>
        /// <returns>index</returns>
        public int GetIndexFromLineAndColumn(int line, int column)
        {
            if (line < 0)
                return -1;
            //first get the index of the first char of the specified line
            int firstCharLineIndex = richTextBoxCtrl.GetFirstCharIndexFromLine(line);
            if (firstCharLineIndex < 0)
                return -1;

            return firstCharLineIndex + column;
        }

        #region Macro Recording methods
        public void RecordDelete(bool backspace, bool word)
        {
            // If not backspace then it's a delete
            // If not word then it's a single character
            LastMacro macroType = backspace ?
                    (word ? LastMacro.BackspaceWord : LastMacro.BackspaceChar) :
                    (word ? LastMacro.DeleteWord : LastMacro.DeleteChar);

            // Get the number of times the macro type calculated above has been recorded already
            // (if any) and then add one to get the current count
            uint count = m_Recorder.GetTimesPreviouslyRecorded(macroType) + 1;

            string macroString = "";
            // if this parameter is negative, it indicates a backspace, rather then a delete
            macroString += "ActiveDocument.Object.Delete(" + (int)(word ? tom.tomConstants.tomWord : tom.tomConstants.tomCharacter) + ", " + (backspace ? -1 * count : count) + ")";

            m_Recorder.RecordBatchedLine(macroType, macroString);
        }

        public void RecordMove(LastMacro state, string direction, MoveScope scope, bool extend)
        {

            string macroString = "";
            macroString += "ActiveDocument.Object.Move";
            macroString += direction;
            // Get the number of times this macro type has been recorded already
            // (if any) and then add one to get the current count
            macroString += "(" + (int)scope + ", " + (m_Recorder.GetTimesPreviouslyRecorded(state) + 1) + ", " + (int)(extend ? tom.tomConstants.tomExtend : tom.tomConstants.tomMove) + ")";

            m_Recorder.RecordBatchedLine(state, macroString);
        }

        public void RecordCommand(string command)
        {
            if (m_Recorder.IsRecording())
            {
                string line = "ActiveDocument.Object.";

                line += command;

                m_Recorder.RecordLine(line);
            }
        }
        
        public void StopRecorder()
        {
            m_Recorder.Stop();
        }

        public void RecordPrintableChar(char currentValue)
        {
            string macroString = "";

            if (!m_Recorder.IsLastRecordedMacro(LastMacro.Text))
            {
                m_TextToRecord = "";
            }

            // Only deal with text characters.  Everything, space and above is a text chracter
            // except DEL (0x7f).  Include carriage return (enter key) and tab, which are
            // below space, since those are also text characters.
            if (char.IsLetterOrDigit(currentValue) ||
                    char.IsPunctuation(currentValue) ||
                    char.IsSeparator(currentValue) ||
                    char.IsSymbol(currentValue) ||
                    char.IsWhiteSpace(currentValue) ||
                    '\r' == currentValue || '\t' == currentValue)
            {
                if ('\r' == currentValue)
                {
                    // Emit "\r\n" as the standard line terminator
                    m_TextToRecord += "\" & vbCr & \"";
                }
                else if ('\t' == currentValue)
                {
                    // Emit "\t" as the standard tab
                    m_TextToRecord += "\" & vbTab & \"";
                }
                else
                {
                    m_TextToRecord += currentValue;
                }

                macroString += "ActiveDocument.Object.TypeText(\"";
                macroString += m_TextToRecord;
                macroString += "\")";

                if (m_Recorder.RecordBatchedLine(LastMacro.Text, macroString, 100)) // arbitrary max length
                {
                    // Clear out the buffer if the line hit max length, since
                    // it will not continue to be appended to
                    m_TextToRecord = "";
                }
            }       
        }
        
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
        public void RecordNonprintableChar(Keys currentKey)
        {
            string macroString = "";

            // Obtain the CTRL and SHIFT as they modify a number of the virtual keys. 
            bool shiftDown = System.Windows.Forms.Keys.Shift == (System.Windows.Forms.Control.ModifierKeys & System.Windows.Forms.Keys.Shift); //Keyboard::IsKeyDown(VK_SHIFT);
            bool controlDown = System.Windows.Forms.Keys.Control == (System.Windows.Forms.Control.ModifierKeys & System.Windows.Forms.Keys.Control); //Keyboard::IsKeyDown(VK_CONTROL);

            // msg.WParam indicates the virtual key.
            switch (currentKey)
            {
                case Keys.Back: // BackSpace key
                    // Note that SHIFT does not affect this command
                    RecordDelete(true, controlDown);
                    break;

                case Keys.Delete:
                    // Note that SHIFT completely disables this command
                    if (!shiftDown)
                    {
                        RecordDelete(false, controlDown);
                    }
                    break;

                case Keys.Left: // Left Arrow
                    // SHIFT indicates selection, CTRL indicates words instead of characters
                    {
                        LastMacro macroType = controlDown ?
                        (shiftDown ? LastMacro.LeftArrowWordSelection : LastMacro.LeftArrowWord) :
                        (shiftDown ? LastMacro.LeftArrowCharSelection : LastMacro.LeftArrowChar);

                        RecordMove(macroType, "Left", controlDown ? MoveScope.Word : MoveScope.Character, shiftDown);
                    }
                    break;

                case Keys.Right: // Right Arrow
                    // SHIFT indicates selection, CTRL indicates words instead of characters
                    {
                        LastMacro macroType = controlDown ?
                        (shiftDown ? LastMacro.RightArrowWordSelection : LastMacro.RightArrowWord) :
                        (shiftDown ? LastMacro.RightArrowCharSelection : LastMacro.RightArrowChar);

                        RecordMove(macroType, "Right", controlDown ? MoveScope.Word : MoveScope.Character, shiftDown);
                    }
                    break;

                case Keys.Up: // Up Arrow
                    // SHIFT indicates selection, CTRL indicates paragraphs instead of lines
                    {
                        LastMacro macroType = controlDown ?
                        (shiftDown ? LastMacro.UpArrowParaSelection : LastMacro.UpArrowPara) :
                        (shiftDown ? LastMacro.UpArrowLineSelection : LastMacro.UpArrowLine);

                        RecordMove(macroType, "Up", controlDown ? MoveScope.Paragraph : MoveScope.Line, shiftDown);
                    }
                    break;

                case Keys.Down: // Down Arrow
                    // SHIFT indicates selection, CTRL indicates paragraphs instead of lines
                    {
                        LastMacro macroType = controlDown ?
                        (shiftDown ? LastMacro.DownArrowParaSelection : LastMacro.DownArrowPara) :
                        (shiftDown ? LastMacro.DownArrowLineSelection : LastMacro.DownArrowLine);

                        RecordMove(macroType, "Down", controlDown ? MoveScope.Paragraph : MoveScope.Line, shiftDown);
                    }
                    break;

                case Keys.Prior: // Page Up
                case Keys.Next: // Page Down
                    macroString += "ActiveDocument.Object.Move";

                    if (System.Windows.Forms.Keys.Prior == currentKey)
                    {
                        macroString += "Up";
                    }
                    else
                    {
                        macroString += "Down";
                    }

                    macroString += "(" + (int)(controlDown ? tom.tomConstants.tomWindow : tom.tomConstants.tomScreen) + ", 1, " + (int)(shiftDown ? tom.tomConstants.tomExtend : tom.tomConstants.tomMove) + ")";

                    m_Recorder.RecordLine(macroString);
                    break;

                case Keys.End:
                case Keys.Home:
                    macroString += "ActiveDocument.Object.";

                    if (System.Windows.Forms.Keys.End == currentKey)
                    {
                        macroString += "EndKey";
                    }
                    else
                    {
                        macroString += "HomeKey";
                    }

                    macroString += "(" + (int)(controlDown ? tom.tomConstants.tomStory : tom.tomConstants.tomLine) + ", " + (int)(shiftDown ? tom.tomConstants.tomExtend : tom.tomConstants.tomMove) + ")";

                    m_Recorder.RecordLine(macroString);
                    break;

                case Keys.Insert:
                    // Note that the CTRL completely disables this command.  Also the SHIFT+INSERT
                    // actually generates a WM_PASTE message rather than a WM_KEYDOWN
                    if (!controlDown)
                    {
                        macroString = "ActiveDocument.Object.Flags = ActiveDocument.Object.Flags Xor ";
                        macroString += (int)tom.tomConstants.tomSelOvertype;
                        m_Recorder.RecordLine(macroString);
                    }
                    break;
            }
        }

        // This event returns the literal key that was pressed and does not account for
        // case of characters.  KeyPress is used to handled printable caracters.
        private void richTextBoxCtrl_KeyDown(object sender, KeyEventArgs e)
        {
            if (m_Recorder.IsRecording())
            {
                RecordNonprintableChar(e.KeyCode);
            }
        }

        // The argumements of this event will give us the char value of the key press taking into
        // account other characters press such as shift or caps lock for proper casing.
        private void richTextBoxCtrl_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (m_Recorder.IsRecording())
            {
                RecordPrintableChar(e.KeyChar);
            }
        }
        #endregion

        private void richTextBoxCtrl_MouseEnter(object sender, EventArgs e)
        {
            if(m_Recorder.IsRecording())
                richTextBoxCtrl.FilterMouseClickMessages = true;
            else
                richTextBoxCtrl.FilterMouseClickMessages = false;
        }

        private void rulXGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (DataGridViewControl.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
            {
                FieldUpdatedValue = DataGridViewControl.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
                KeyFieldName = DataGridViewControl.Rows[e.RowIndex].Cells[e.ColumnIndex].OwningColumn.HeaderText;
                RuleID = DataGridViewControl.Rows[e.RowIndex].Cells["RuleID"].Value.ToString();



                objRulXAtt.KeyField = KeyFieldName;
                objRulXAtt.KeyFieldNewValue = FieldUpdatedValue;
                objRulXAtt.RuleID = RuleID;

                objRuleXAttributeList.Add(objRulXAtt); 
            }
            

            if(OnDocumentChanged!=null)
            {
                OnDocumentChanged(this, EventArgs.Empty);
            }
        }

        public event EventHandler OnDocumentChanged;

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void rulXGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {

            try
            {
                objRulXAtt = new RulXAttributeObject();
                if (DataGridViewControl.Rows[e.RowIndex].Cells[e.ColumnIndex].Value!=null)
                {
                    
                    FieldOldValue = DataGridViewControl.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
                    objRulXAtt.KeyFieldOldValue = FieldOldValue; 
                }

            }
            
            catch (System.Data.ReadOnlyException readOnlyEx)
            {

                MessageBox.Show(readOnlyEx.Message);
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message); ;
            }
        }

        bool newRowNeeded;
        private void rulXGridView_NewRowNeeded(object sender, DataGridViewRowEventArgs e)
        {
            newRowNeeded = true;
            //MessageBox.Show(GetRuleXFieldList()[0].ToString());
            //Storing newly added row index
            NewAddedRowIndex = e.Row.Index;
            //SetRuleXFieldList();

            //Action = RulXActionEnum.RULXADD;
            
        }


        private void rulXGridView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            try
            {
                if (newRowNeeded)
                {
                    newRowNeeded = false;
                    DataGridViewControl.Rows[e.RowIndex - 1].Cells["RuleID"].Value = GetNewRuleID().ToString();
                    NewRuleID = GetNewRuleID().ToString();
                    
                }
            }
            catch (Exception ex)
            {
                
                MessageBox.Show(ex.Message);
            }
        }

        private int GetNewRuleID()
        {
            int nextRowID = 0;
            
            nextRowID = Convert.ToInt32(DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 3].Cells["RuleID"].Value);

            nextRowID++;

            return nextRowID;
        }


        private void SetRuleXFieldList(int rowIndex)
        {
            try
            {
                objRulXFieldList = new Dictionary<string,string>();
                //objRuleXFieldList = new Dictionary<string, Dictionary<string,string>>();
                //objRulXFieldList.Clear();

                string strDataType = string.Empty;
                string strDataOutput = string.Empty;
                string strFieldValue = string.Empty;
                string strDataTypeAndOuputTypeVal = string.Empty;

                if (objRuleXFieldList.ContainsKey(NewRuleID))
                {
                    return;
                }
                

                foreach (DataGridViewColumn dgvc in DataGridViewControl.Columns)
                {
                    
                    if (!dgvc.HeaderText.ToUpper().Trim().Equals("RULEID"))
                    {
                        strDataTypeAndOuputTypeVal = DataGridViewControl.Rows[0].Cells[dgvc.HeaderText.Trim()].Value.ToString();
                        IList<string> objList = strDataTypeAndOuputTypeVal.Split(' ');

                        strDataType = objList[0];
                        strDataOutput = objList[1].Substring(1, objList[1].Length-2);


                        if (DataGridViewControl.Rows[rowIndex].Cells[dgvc.HeaderText.Trim()].Value != null)
                        {
                            strFieldValue = DataGridViewControl.Rows[rowIndex].Cells[dgvc.HeaderText.Trim()].Value.ToString(); 
                        }
                        //strDataType = DataGridViewControl.Rows[0].Cells[dgvc.HeaderText.Trim()].Value.ToString();

                        objRulXFieldList.Add(dgvc.HeaderText.Trim(), strFieldValue + "|" + strDataType + "|" + strDataOutput);
                        //DataGridViewControl.Rows[NewAddedRowIndex].Cells[dgvc.HeaderText.Trim()].Value.ToString()

                    }
                }
                //objRuleXFieldList.Clear();
                objRuleXFieldList.Add(NewRuleID, objRulXFieldList);

                
            }
            catch (ArgumentNullException argNullEx)
            {

                throw argNullEx;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        private void rulXGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            rulXGridView.Rows[e.RowIndex].ErrorText = "";
            int newInteger;

            // Don't try to validate the 'new row' until finished 
            // editing since there
            // is not any point in validating its initial value.
            if (rulXGridView.Rows[e.RowIndex].IsNewRow) { return; }
            //if (e.FormattedValue.ToString().Length == 0)
            //{
            //    e.Cancel = true;
            //    rulXGridView.Rows[e.RowIndex].ErrorText = "Please enter the required value";
            //    //rulXGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Please enter the required value";

            //}
            //else
            //{
            //    //if((!int.TryParse(e.FormattedValue.ToString(), out newInteger) || newInteger < 0))
            //    //{

            //    //}
            //    e.Cancel = false;
            //}

            string strDataType = rulXGridView.Rows[0].Cells[e.ColumnIndex].Value.ToString();
            bool bIsNullAllowed = rulXGridView.Rows[0].Cells[e.ColumnIndex].Value.ToString().Contains("null");

            if (e.ColumnIndex != 0)
            {
                if (!bIsNullAllowed)
                {
                    if (!string.IsNullOrEmpty(strDataType))
                    {
                        if (strDataType.Trim().ToUpper().StartsWith("STRING") && IsNumeric(e.FormattedValue.ToString()))
                        {
                            e.Cancel = true;
                            rulXGridView.Rows[e.RowIndex].ErrorText = "Please enter the text value";
                            //rulXGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Please enter the required value";

                        }
                        else if ((strDataType.Trim().ToUpper().StartsWith("INT") || strDataType.Trim().ToUpper().StartsWith("DOUBLE")) && !IsNumeric(e.FormattedValue.ToString()))
                        {
                            e.Cancel = true;
                            rulXGridView.Rows[e.RowIndex].ErrorText = "Please enter the numeric value";
                            //rulXGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Please enter the required value";

                        }
                        else if (strDataType.Trim().ToUpper().StartsWith("BOOLEAN") && !IsBoolean(e.FormattedValue.ToString()))
                        {
                            e.Cancel = true;
                            rulXGridView.Rows[e.RowIndex].ErrorText = "Please enter the boolean value";
                            //rulXGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Please enter the required value";

                        }
                        else
                        {
                            //if((!int.TryParse(e.FormattedValue.ToString(), out newInteger) || newInteger < 0))
                            //{

                            //}
                            e.Cancel = false;
                        }
                    } 
                } 
            }
        }

        private bool IsNumeric(string strVal)
        {
            // Return true if this is a number.
            int iNumber;
            double dNumber;
            return (int.TryParse(strVal, out iNumber) || double.TryParse(strVal, out dNumber));

        }

        private bool IsBoolean(string strVal)
        {
            // Return true if this is a number.
            bool bVal;
            
            return bool.TryParse(strVal, out bVal);

        }

        private void rulXGridView_RowLeave(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (NewAddedRowIndex == e.RowIndex)
                {
                    //Do the Row Addition logic
                    //set the RulX field list
                    SetRuleXFieldList(NewAddedRowIndex);
                    
                }

                if (NewAddedRowIndex != -1)
                {
                    Action = RulXActionEnum.RULXADD;
                }
                else
                {
                    Action = RulXActionEnum.RULXEDIT;
                }
            }
            catch (ArgumentNullException ex)
            {
                
                MessageBox.Show(ex.Message);
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        

        public bool CheckIfRulXGridValidated()
        {
            bool isValidated = true;
            //replace this.dataGridView1 with the name of your datagridview control 
            foreach (DataGridViewRow row in this.rulXGridView.Rows)
            {
                foreach (DataGridViewCell cell in row.Cells)
                {
                    if (cell.ErrorText.Length > 0)
                    {
                        isValidated = false;
                        break;
                    }
                }
                if (!isValidated)
                    break;
            }

            return isValidated;
        } 


        private void rulXGridView_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
        {
            try
            {
                DataGridViewRow row = rulXGridView.Rows[e.RowIndex];

                // Don't try to validate the 'new row' until finished 
                // editing since there
                // is not any point in validating its initial value.
                if (rulXGridView.Rows[e.RowIndex].IsNewRow) { return; }

                //foreach (DataGridViewColumn colItem in rulXGridView.Columns)
                //{
                //    DataGridViewCell cell = row.Cells[colItem.HeaderText.Trim()];
                //    //if (cell.RowIndex <= NewAddedRowIndex)
                //    //{
                //    if (cell.Value.ToString().Length == 0
                //        || cell.Value == DBNull.Value)
                //    {
                //        cell.ErrorText = "Please enter " + colItem.HeaderText.Trim() + " value";
                //        rulXGridView.Rows[cell.RowIndex].ErrorText = "Please enter the required value";
                //        e.Cancel = true;
                //        //IsNewRowValidated = false;
                //    }
                //    else
                //    {
                //        cell.ErrorText = string.Empty;
                //        rulXGridView.Rows[cell.RowIndex].ErrorText = string.Empty;
                //        e.Cancel = false;
                //        //IsNewRowValidated = true;

                //    }
                //    //}
                //}
                //set the RulX field list
                //SetRuleXFieldList();
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        private void rulXGridView_Leave(object sender, EventArgs e)
        {
            if (!IsNewRowValidated)
            {
                MessageBox.Show("Please enter all required values before save","Error Save",MessageBoxButtons.OK,MessageBoxIcon.Error);
            }
        }

        private void InitializeContextMenu()
        {
            // Create the menu item.
            ToolStripMenuItem ctxMenuCut = new ToolStripMenuItem("Cut", null,
                new System.EventHandler(ShortcutMenuClickCut));
            ToolStripMenuItem ctxMenuCopy = new ToolStripMenuItem("Copy", null,
                new System.EventHandler(ShortcutMenuClickCopy));
            ToolStripMenuItem ctxMenuPaste = new ToolStripMenuItem("Paste", null,
                new System.EventHandler(ShortcutMenuClickPaste));
            //ToolStripMenuItem ctxMenuDelete = new ToolStripMenuItem("Delete", null,
            //    new System.EventHandler(ShortcutMenuClickDelete));
            ToolStripMenuItem ctxMenuRemoveRow = new ToolStripMenuItem("Remove Row", null,
                new System.EventHandler(ShortcutMenuClickRemoveRow));
            
            // Add the menu item to the shortcut menu.
            ContextMenuStrip ctxDashboardMenu = new ContextMenuStrip();
            ctxDashboardMenu.Items.Add(ctxMenuCut);
            ctxDashboardMenu.Items.Add(ctxMenuCopy);
            ctxDashboardMenu.Items.Add(ctxMenuPaste);
            //ctxDashboardMenu.Items.Add(ctxMenuDelete);
            ctxDashboardMenu.Items.Add(ctxMenuRemoveRow);
            
            rulXGridView.ContextMenuStrip = ctxDashboardMenu;
            rulXGridView.MouseDown += new MouseEventHandler(rulXGridView_MouseDown);
        }

        private DataGridViewCell clickedCell;

        private void rulXGridView_MouseDown(object sender, MouseEventArgs e)
        {
            // If the user right-clicks a cell, store it for use by the shortcut menu.
            if (e.Button == MouseButtons.Right)
            {
                if (rulXGridView.SelectedCells.Count > 0)
                {
                    clickedCell = rulXGridView.SelectedCells[0];
                }
                else
                {
                    
                }
            }
            else
            {
                return;
            }
        }

        private void ShortcutMenuClickCut(object sender, System.EventArgs e)
        {
            try
            {
                
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        private void ShortcutMenuClickCopy(object sender, System.EventArgs e)
        {
            try
            {
                if (rulXGridView.GetCellCount(DataGridViewElementStates.Selected) > 0)
                {
                    Clipboard.SetDataObject(rulXGridView.GetClipboardContent());

                }
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        private void ShortcutMenuClickPaste(object sender, System.EventArgs e)
        {
            try
            {
                PasteRulXRow();

            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        private void PasteRulXRow()
        {
            //MessageBox.Show(Clipboard.GetText());
            IList<string> objdataList = Clipboard.GetText().Split('\t');

            int index = rulXGridView.SelectedRows[0].Index;
            RulXPasteRowIndex = index;
            NewAddedRowIndexOnPaste = index;
            //heck if the row already has ruleID in place
            if (rulXGridView.Rows[index].Cells[0].Value != null)
            {
                string strRuleID = rulXGridView.Rows[index].Cells[0].Value.ToString();
                //rulXGridView.Rows.RemoveAt(rulXGridView.Rows.Count - 1);
            }
            else
            {
                int nextRowID = 0;

                nextRowID = Convert.ToInt32(DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 2].Cells["RuleID"].Value);

                nextRowID++;
                rulXGridView.Rows.Add();
                DataGridViewControl.Rows[index].Cells["RuleID"].Value = nextRowID.ToString();
                NewRuleID = nextRowID.ToString();
                DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 3].Cells["RuleID"].Value = (nextRowID - 1).ToString();

            }

            objRuleXAttributeList.Clear();

            foreach (DataGridViewColumn col in DataGridViewControl.Columns)
            {
                if (!col.HeaderText.ToUpper().Trim().Equals("RULEID"))
                {
                    if (RulXPasteRowIndex != DataGridViewControl.Rows.Count - 2)
                    {
                        objRulXAtt = new RulXAttributeObject();
                        objRulXAtt.KeyFieldOldValue = DataGridViewControl.Rows[RulXPasteRowIndex].Cells[col.Index].Value.ToString();
                        objRulXAtt.KeyField = DataGridViewControl.Rows[RulXPasteRowIndex].Cells[col.Index].OwningColumn.HeaderText;
                        objRulXAtt.RuleID = DataGridViewControl.Rows[RulXPasteRowIndex].Cells["RuleID"].Value.ToString();


                        rulXGridView.Rows[index].Cells[col.Index].Value = objdataList[col.Index];

                        objRulXAtt.KeyFieldNewValue = DataGridViewControl.Rows[RulXPasteRowIndex].Cells[col.Index].Value.ToString();

                        objRuleXAttributeList.Add(objRulXAtt);
                    }
                    else
                    {
                        rulXGridView.Rows[index].Cells[col.Index].Value = objdataList[col.Index];
                    }
                }
            }

            if (RulXPasteRowIndex != DataGridViewControl.Rows.Count - 2)
            {
                Action = RulXActionEnum.RULXEDIT;
            }
            else
            {
                Action = RulXActionEnum.RULXADD;
                SetRuleXFieldList(NewAddedRowIndexOnPaste);
            }

            DataGridViewControl.CurrentCell = DataGridViewControl.Rows[index].Cells[DataGridViewControl.Columns.Count - 1];
            this.rulXGridView.BeginEdit(true);
        }

        private void SetRulXAttributeOnPaste(List<RulXAttributeObject> objRulXRowValueList)
        {
            objRuleXAttributeList.Clear();

            foreach (DataGridViewColumn col in DataGridViewControl.Columns)
            {
                objRulXAtt = new RulXAttributeObject();
                FieldUpdatedValue = DataGridViewControl.Rows[RulXPasteRowIndex].Cells[col.Index].Value.ToString();
                KeyFieldName = DataGridViewControl.Rows[RulXPasteRowIndex].Cells[col.Index].OwningColumn.HeaderText;
                RuleID = DataGridViewControl.Rows[RulXPasteRowIndex].Cells["RuleID"].Value.ToString();

                objRulXAtt.KeyField = KeyFieldName;
                objRulXAtt.KeyFieldNewValue = FieldUpdatedValue;
                objRulXAtt.RuleID = RuleID;

                objRuleXAttributeList.Add(objRulXAtt);  
            }
        }

        private void ShortcutMenuClickDelete(object sender, System.EventArgs e)
        {
            try
            {

            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        public event EventHandler OnRulXRowRemoved;

        private void ShortcutMenuClickRemoveRow(object sender, System.EventArgs e)
        {
            try
            {
                RemoveRulXRow();
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

        private void RemoveRulXRow()
        {
            XMLRecordGenerator objXmlRecGen = new XMLRecordGenerator();

            string strRuleID = string.Empty;
            List<string> ruleIDList = new List<string>();
            //Get the selected rule ID
            //string strRuleID = rulXGridView.SelectedRows[0].Cells["RuleID"].Value.ToString();
            DataGridViewSelectedRowCollection dgvrCollection = rulXGridView.SelectedRows;

            if (MessageBox.Show("Are you sure you want to Remove the selected Rule/s?", "Alert", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
            {
                if (dgvrCollection != null && dgvrCollection.Count > 0)
                {

                    foreach (DataGridViewRow dgvr in dgvrCollection)
                    {
                        strRuleID = dgvr.Cells["RuleID"].Value.ToString();
                        ruleIDList.Add(strRuleID);
                    }

                    objXmlRecGen.RemoveRulXData(RulXFile, ruleIDList);


                    this.toolStripButtonDelRule.Enabled = false;
                }
                else
                {
                    if (ClickedRowIndex != 0 && ClickedRowIndex != -1)
                    {
                        strRuleID = rulXGridView.Rows[ClickedRowIndex].Cells["RuleID"].Value.ToString();
                        ruleIDList.Add(strRuleID);
                    }
                    objXmlRecGen.RemoveRulXData(RulXFile, ruleIDList);
                }
            }
            else
            {
                return;
            }

            if (OnRulXRowRemoved != null)
            {
                OnRulXRowRemoved(this, EventArgs.Empty);
            } 
        }

        private void toolStripButton1_MouseHover(object sender, EventArgs e)
        {
            //toolStripButton1.BackColor = System.Drawing.Color.Orange;
        }
        private void toolStripButton2_MouseHover(object sender, EventArgs e)
        {
            //toolStripButton2.BackColor = System.Drawing.Color.Orange;
        }

        private void rulXGridView_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            ClickedRowIndex = e.RowIndex;
        }

        private void rulXGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (this.rulXGridView != null)
            {
                Point point1 = this.rulXGridView.CurrentCellAddress;
                if (point1.X == e.ColumnIndex &&
                    point1.Y == e.RowIndex &&
                    e.Button == MouseButtons.Left &&
                    this.rulXGridView.EditMode !=
                    DataGridViewEditMode.EditProgrammatically)
                {
                    this.rulXGridView.BeginEdit(true);
                }
            }
        }

        private void rulXGridView_RowValidated(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void toolStripButtonAddRule_Click(object sender, EventArgs e)
        {
            try
            {
                int nextRowID = 0;

                newRowNeeded = true;
                int newRowIndex = DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 1].Index;

                NewAddedRowIndex = newRowIndex;
                //SetRuleXFieldList();

                nextRowID = Convert.ToInt32(DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 2].Cells["RuleID"].Value);

                nextRowID++;
                rulXGridView.Rows.Add();
                DataGridViewControl.Rows[DataGridViewControl.Rows.Count-2].Cells["RuleID"].Value = nextRowID.ToString();
                NewRuleID = nextRowID.ToString();
                DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 3].Cells["RuleID"].Value = (nextRowID - 1).ToString();

                DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 3].Selected = false;
                //DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 2].Selected = true;
                DataGridViewControl.Rows[0].Cells[0].Selected = false;
                //DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 2].Cells[1].ed
                DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 2].Cells[1].Value = "<Value>";
                DataGridViewControl.CurrentCell = DataGridViewControl.Rows[DataGridViewControl.Rows.Count - 2].Cells[1];
                this.rulXGridView.BeginEdit(true);

            }
            catch (Exception ex)
            {
                
                MessageBox.Show(ex.Message);
            }
                    
        }

        
        private void rulXGridView_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            ClickedRowIndex = e.RowIndex;
        }

        private void toolStripButtonDelRule_Click(object sender, EventArgs e)
        {
            RemoveRulXRow();
        }

        private void rulXGridView_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            
            //Check if this row is intended to be a new row then essentially set the newrowindex value 
            //and subseqiently set the new ruleid value
            if (e.RowIndex == DataGridViewControl.Rows.Count - 1)
            {
                newRowNeeded = true;
                NewAddedRowIndex = e.RowIndex;

                this.toolStripButtonDelRule.Enabled = false;
            }
            else
            {
                if (e.RowIndex!=0)
                {
                    this.toolStripButtonDelRule.Enabled = true;
                }
                else
                {
                    this.toolStripButtonDelRule.Enabled = false;
                }
            }
        }

        
    }
}
